import re

from django.conf import settings
from django_redis import get_redis_connection
from rest_framework import serializers
from rest_framework_jwt.settings import api_settings

from oauth.models import OAuthQQUser
from users.models import User

from itsdangerous import TimedJSONWebSignatureSerializer as TJS


class QQAuthUserSerializer(serializers.ModelSerializer):
    # 不是模型类字段需要显示指明
    sms_code = serializers.CharField(max_length=6, min_length=6, write_only=True)
    access_token = serializers.CharField(write_only=True)
    # 如果模型类中的字段生成的序列化字段不能满足需求时，可以重写
    mobile = serializers.RegexField(label='手机号', regex=r'^1[3-9]\d{9}$')
    token = serializers.CharField(read_only=True)

    class Meta:
        model = User
        fields = ('password', 'mobile', 'sms_code', 'access_token', 'username', 'token')
        read_only_fields = ('username', )  # 指定只读字段,序列化返回
        extra_kwargs = {
            'password': {
                'max_length': 20,
                'min_length': 8,
                'write_only': True,
                'error_messages': {
                    'max_length': '密码过长',
                    'min_length': '密码过短'
                }
            },
            'mobile': {
                'max_length': 11,
                'min_length': 11,
                'error_messages': {
                    'max_length': '手机号错误',
                    'min_length': '手机号错误'
                }
            }
        }

    def validate(self, attrs):
        # access_token验证
        # 解密access_token
        tjs = TJS(settings.SECRET_KEY, 300)
        try:
            data = tjs.loads(attrs['access_token'])
        except:
            raise serializers.ValidationError('错误的access_token')
        openid = data.get('openid')

        # attrs添加额外属性,方便保存数据时进行提取
        attrs['openid'] = openid
        # 短信验证
        # 短信验证
        # 从redis中获取真实短信
        # 1.建立连接
        # 2.获取数据 bytes
        conn = get_redis_connection('verify')
        # 判断是否过期
        real_sms_code = conn.get('sms_%s' % attrs['mobile'])
        if not real_sms_code:
            raise serializers.ValidationError('短信失效')

        # 3.转换数据
        real_sms_code = real_sms_code.decode()

        # 4.比对验证
        if real_sms_code != attrs['sms_code']:
            raise serializers.ValidationError('短信错误')

        # 用户验证
        try:
            user = User.objects.get(mobile=attrs['mobile'])
        except:
            return attrs
        else:
            if user.check_password(attrs['password']):
                attrs['user'] = user
                return attrs
            else:
                raise serializers.ValidationError('密码错误')

    def create(self, validated_data):
        # 获取user判断用户是否注册
        user = validated_data.get('user', None)
        if not user:
            # 用户未注册,进行注册
            user = User.objects.create_user(username=validated_data['mobile'], password=validated_data['password'], mobile=validated_data['mobile'])
        # 用户注册过,绑定用户
        OAuthQQUser.objects.create(user=user, openid=validated_data['openid'])

        # 生成token
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)

        # 给对象添加额外属性，序列化返回时必须要在序列化器中显示指明token字段
        user.token = token

        return user